﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
using Newtonsoft.Json.Linq;

namespace EloamDllDemo
{
    using BOOL = Int32;
    using COLORREF = UInt32;
    using HELOAMBASE64 = IntPtr;
    using HELOAMDEVICE = IntPtr;
    using HELOAMFONT = IntPtr;
    using HELOAMFTP = IntPtr;
    using HELOAMHTTP = IntPtr;
    using HELOAMIMAGE = IntPtr;
    using HELOAMIMAGELIST = IntPtr;
    using HELOAMMEMORY = IntPtr;
    using HELOAMRECT = IntPtr;
    using HELOAMTHUMBNAIL = IntPtr;
    using HELOAMVIDEO = IntPtr;
    using HELOAMVIDEOCAP = IntPtr;
    using HELOAMVIEW = IntPtr;
    using HWND = IntPtr;
    using LONG = Int32;
    using LPVOID = IntPtr;

    // callback
    public delegate void ELOAM_DEVCHANGECALLBACK(LONG type, LONG idx, LONG dbt, LPVOID userData);
    public delegate void ELOAM_ARRIVALCALLBACK(HELOAMVIDEO video, LONG id, LPVOID userData);
    public delegate void ELOAM_TOUCHCALLBACK(HELOAMVIDEO video, LPVOID userData);
    public delegate void ELOAM_MOVEDETECCALLBACK(HELOAMVIDEO video, LONG id, LPVOID userData);
    public delegate void ELOAM_ATTACHCALLBAK(
        HELOAMVIDEO video,
        LONG videoId,
        HELOAMVIEW view,
        LONG viewId,
        LPVOID userData
    );

    public delegate void ELOAM_IDCARDCHANGECALLBACK(LONG dbt, LPVOID userData);

    public partial class Form1 : Form
    {
        HELOAMVIEW m_hView;
        HELOAMTHUMBNAIL m_hThumb;

        //设别列表（专指视频）
        List<HELOAMDEVICE> m_vDevice;
        HELOAMVIDEO m_hVideo;
        HELOAMVIDEOCAP m_cap;

        //合成时的临时图片
        HELOAMIMAGE m_hImageTemp;

        //定义系统计时器
        private System.Timers.Timer timer;
        private int timer_value;

        ELOAM_DEVCHANGECALLBACK DevChangeCallBack;
        ELOAM_ATTACHCALLBAK attachCallback;

        private string ImageFolderPath = Path.Combine(
            AppDomain.CurrentDomain.BaseDirectory,
            ImageFolderName
        );

        public static string ImageFolderName =
            ConfigurationManager.AppSettings["ImageFolderName"] ?? "";

        //public string ImageFolderPath =
        //    ConfigurationManager.AppSettings["PicImageTempLocalPath"] ?? "";

        public int CamIndex = int.TryParse(
            ConfigurationManager.AppSettings["CamIndex"],
            out int canResult
        )
            ? canResult
            : 0;

        public Form1()
        {
            InitializeComponent();
            m_hView = IntPtr.Zero;
            m_hThumb = IntPtr.Zero;
            m_hView = IntPtr.Zero;
            m_hImageTemp = IntPtr.Zero;
            m_vDevice = new List<HELOAMDEVICE>();

            timer_value = 5;
            Width = 800;
            Height = 610;
            MaximizeBox = false;
            MinimizeBox = false;

            Init();

            /*openVideo_Click(new object(), new EventArgs());*/
        }

        public void Init()
        {
            //清空ImageFolderPath 文件夹下方的文件
            if (Directory.Exists(ImageFolderPath))
            {
                DirectoryInfo di = new DirectoryInfo(ImageFolderPath);
                foreach (FileInfo file in di.GetFiles())
                {
                    file.Delete();
                }
            }
            else
            {
                Directory.CreateDirectory(ImageFolderPath);
            }

            m_hView = EloamDll.EloamGlobal_CreateView(eloamView.Handle, IntPtr.Zero, 0);
            m_hThumb = EloamDll.EloamGlobal_CreateThumbnail(eloamThumbnail.Handle, IntPtr.Zero, 0);

            DevChangeCallBack = new ELOAM_DEVCHANGECALLBACK(DEVCHANGECALLBACK);
            EloamDll.EloamGlobal_InitDevs(DevChangeCallBack, this.Handle);

            if (1 != EloamDll.EloamGlobal_VideoCapInit())
            {
                MessageBox.Show("初始化视频录像失败！");
            }

            selectDevice.SelectedIndex = CamIndex;
            selectResolution.SelectedIndex = 4;
            selectDevice.Enabled = false;
            selectResolution.Enabled = false;
            selectMode.Enabled = false;
            OpenVideoFunc();
        }

        public void DEVCHANGECALLBACK(LONG type, LONG idx, LONG dbt, LPVOID userData)
        {
            if (1 != type) // 只处理视频设备
                return;

            if (1 == dbt) // 设备到达
            {
                HELOAMDEVICE hDev = EloamDll.EloamGlobal_CreateDevice(1, idx);
                m_vDevice.Add(hDev);

                // 显示到界面
                IntPtr temp = EloamDll.EloamDevice_GetFriendlyName(hDev);
                string wName = Marshal.PtrToStringAuto(temp);
                selectDevice.Items.Add(wName);

                //销毁字符串所占空间
                EloamDll.EloamGlobal_DestroyString(temp);

                if (-1 == selectDevice.SelectedIndex)
                {
                    selectDevice.SelectedIndex = 0; //改变所选设备
                }

                selectDevice_SelectedIndexChanged(new object(), new EventArgs());
            }
            else if (2 == dbt) // 设备丢失
            {
                int realIdx = -1;
                for (int i = 0; i < m_vDevice.Count(); i++)
                {
                    if (idx == EloamDll.EloamDevice_GetIndex(m_vDevice[i]))
                    {
                        realIdx = i;
                        break;
                    }
                }

                if (realIdx == -1)
                {
                    return;
                }

                HELOAMDEVICE hDevTemp = EloamDll.EloamVideo_GetDevice(m_hVideo);
                if (m_vDevice[realIdx] == hDevTemp)
                {
                    closeVideo_Click(new object(), new EventArgs());
                }

                EloamDll.EloamDevice_Release(hDevTemp);
                EloamDll.EloamDevice_Release(m_vDevice[realIdx]);

                m_vDevice.RemoveAt(realIdx);
                selectDevice.Items.RemoveAt(realIdx);

                if (-1 == selectDevice.SelectedIndex)
                {
                    selectDevice.Text = null;
                    if (0 != m_vDevice.Count)
                    {
                        selectDevice.SelectedIndex = 0;
                    }
                    else
                    {
                        selectMode.Items.Clear();
                        selectResolution.Items.Clear();
                    }
                }
            }
        }

        private void closeVideo_Click(object sender, EventArgs e)
        {
            EloamDll.EloamView_SetText(m_hView, null, 0);
            EloamDll.EloamVideo_Release(m_hVideo);
            m_hVideo = IntPtr.Zero;

            EloamDll.EloamImage_Release(m_hImageTemp);
            m_hImageTemp = IntPtr.Zero;

            //kill timer
            if (null != timer)
            {
                timer.Stop();
                timer.Enabled = false;
            }
        }

        public uint RGB(uint r, uint g, uint b)
        {
            return (((b << 16) | (g << 8)) | r);
        }

        private void OpenVideoFunc()
        {
            int devIdx = selectDevice.SelectedIndex;
            int resIdx = selectResolution.SelectedIndex;
            string curModeString = selectMode.SelectedItem.ToString();
            int modeIdx = (
                curModeString == "YUY2"
                    ? 1
                    : (curModeString == "MJPG" ? 2 : (curModeString == "UYVY" ? 4 : -1))
            );

            if (-1 != devIdx)
            {
                EloamDll.EloamVideo_Release(m_hVideo);

                HELOAMDEVICE hDev = m_vDevice[devIdx];
                m_hVideo = EloamDll.EloamDevice_CreateVideo(
                    hDev,
                    resIdx,
                    modeIdx,
                    null,
                    (IntPtr)0,
                    null,
                    (IntPtr)0,
                    0,
                    2
                );

                if (null != m_hVideo)
                {
                    attachCallback = new ELOAM_ATTACHCALLBAK(ATTACHCALLBAK);
                    EloamDll.EloamView_SelectVideo(m_hView, m_hVideo, attachCallback, this.Handle);
                    EloamDll.EloamView_SetText(m_hView, "打开视频中，请等待...", RGB(255, 255, 255));
                }
            }
        }

        public void ATTACHCALLBAK(
            HELOAMVIDEO video,
            LONG videoId,
            HELOAMVIEW view,
            LONG viewId,
            LPVOID userData
        )
        {
            if (0 == videoId && 0 == viewId) { }
        }

        private void selectDevice_SelectedIndexChanged(object sender, EventArgs e)
        {
            selectMode.Items.Clear();

            int idx = selectDevice.SelectedIndex; //记录当前所选设备
            if (-1 != idx)
            {
                HELOAMDEVICE hDev = m_vDevice[idx];

                //加载模式列表
                LONG subtype = EloamDll.EloamDevice_GetSubtype(hDev);
                if (0 != (subtype & 1))
                {
                    selectMode.Items.Add("YUY2");
                }
                if (0 != (subtype & 2))
                {
                    selectMode.Items.Add("MJPG");
                }
                if (0 != (subtype & 4))
                {
                    selectMode.Items.Add("UYVY");
                }

                //若为辅摄像头，优先选择MJPG方式
                if (1 != EloamDll.EloamDevice_GetEloamType(hDev) && 0 != (subtype & 2))
                {
                    selectMode.SelectedIndex = 1;
                }
                else
                {
                    selectMode.SelectedIndex = 0;
                }

                selectMode_SelectedIndexChanged(new object(), new EventArgs());
            }
        }

        private void selectMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            selectResolution.Items.Clear();
            int idx = selectDevice.SelectedIndex; //记录当前所选设备
            if (-1 != idx)
            {
                HELOAMDEVICE hDev = m_vDevice[idx];

                //加载分辨率列表
                int subtype = -1;
                string curModeString = selectMode.SelectedItem.ToString();
                subtype = (
                    curModeString == "YUY2"
                        ? 1
                        : (curModeString == "MJPG" ? 2 : (curModeString == "UYVY" ? 4 : -1))
                );

                if (-1 != subtype)
                {
                    int count = EloamDll.EloamDevice_GetResolutionCountEx(hDev, subtype);
                    for (int i = 0; i < count; ++i)
                    {
                        LONG width = EloamDll.EloamDevice_GetResolutionWidthEx(hDev, subtype, i);
                        LONG height = EloamDll.EloamDevice_GetResolutionHeightEx(hDev, subtype, i);

                        string str = width + " * " + height;
                        selectResolution.Items.Add(str);
                    }
                    selectResolution.SelectedIndex = 0;
                }
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            closeVideo_Click(new object(), new EventArgs());

            int size = m_vDevice.Count;
            for (int i = 0; i < size; ++i)
            {
                HELOAMDEVICE hDev = m_vDevice[i];
                EloamDll.EloamDevice_Release(hDev);
            }
            EloamDll.EloamGlobal_DeinitFaceDetect();
            EloamDll.EloamThumbnail_Release(m_hThumb);
            EloamDll.EloamView_Release(m_hView);
            EloamDll.EloamGlobal_DeinitBarcode();
            EloamDll.EloamGlobal_DeinitDevs();
            EloamDll.EloamView_SetText(m_hView, null, 0);
            EloamDll.EloamVideo_Release(m_hVideo);
        }

        public void MOVEDETECCALLBACK(HELOAMVIDEO video, LONG id, LPVOID userData)
        {
            shoot_Click(new object(), new EventArgs());
        }

        private void shoot_Click(object sender, EventArgs e)
        {
            HELOAMIMAGE hImg = EloamDll.EloamVideo_CreateImage(m_hVideo, 0, m_hView);

            if (IntPtr.Zero != hImg)
            {
                DateTime dateTime = DateTime.Now;
                string time = DateTime.Now.ToString(
                    "yyyyMMddHHmmss",
                    DateTimeFormatInfo.InvariantInfo
                );
                string filename = Path.Combine(ImageFolderPath, time + ".jpg");

                if (1 == EloamDll.EloamImage_Save(hImg, filename, 0))
                {
                    EloamDll.EloamView_PlayCaptureEffect(m_hView);
                    EloamDll.EloamThumbnail_Add(m_hThumb, filename);
                }

                EloamDll.EloamImage_Release(hImg);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}
